package com.guinea.core.web;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessages;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ReflectionUtils;

import com.guinea.core.Constants;
import com.guinea.core.orm.BaseEntity;
import com.guinea.core.orm.Page;
import com.guinea.core.orm.PropertyFilter;
import com.guinea.core.service.CRUDManager;
import com.guinea.core.utils.BeanUtils;
import com.guinea.core.utils.CommonUtils;


/**
 * 负责管理单个Entity CRUD操作的Struts Action基类.
 * <p/>
 * 子类以以下方式声明,并实现将拥有默认的CRUD函数
 * <p/>
 * 
 * <pre>
 *   public class UserAction extends StrutsEntityAction<User, UserDao> {
 *   	private UserDao userDao;
 * <p/>
 *   	public void setUserDao(UserDao userDao) {
 *   		this.userDao = userDao;
 *   	}
 *   }
 * </pre>
 * <p/>
 * 此类仅演示一种封装的方式，大家可按自己的项目习惯进行重新封装
 * <p/>
 * 目前封装了：<br/>
 * 1.index、list、create、edit、view、save、delete 七种action的流程封装；<br/>
 * 2.doListEntity、doGetEntity、doNewEntity、doSaveEntity(),doDeleteEntity
 * 五种业务函数调用，可在子类重载；<br/>
 * 3.initEntity、initForm两个FormBean与业务对象的初始函数及refrenceData,onInitForm,
 * onInitEntity 三个回调函数；<br/>
 * 4.savedMessage、deletedMessage 两种业务成功信息，可在子类重载。<br/>
 * 
 * @author calvin
 */
public abstract class StrutsEntityAction extends StrutsAction implements
		InitializingBean {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	protected static final String LIST = "list";

	protected static final String EDIT = "edit";
	
	protected static final String VIEW = "view";
	
	protected static final String REQUEST_PAGE = "page";
	
	protected static final String REQUEST_ENTITY = "entity";
	
	protected Class idClass; // Action所管理的Entity的主键类型.

	protected String idName; // Action所管理的Entity的主键名.
	
	protected Serializable id; // Action所管理的Entity的主键值.

	/**
	 * 取得entityClass的函数. 
	 */
	protected Class getEntityClass(){
		return getEntityManager().getEntityDao().getEntityClass();
	};
	
	public abstract CRUDManager getEntityManager() ;

	/**
	 * Init回调函数,初始化一系列参数.
	 */
	public void afterPropertiesSet() {
		// 反射获得entity的主键类型
		try {
			idName = getEntityManager().getEntityDao().getIdName();
			idClass = BeanUtils.getPropertyType(getEntityClass(), idName);
		} catch (Exception e) {
			ReflectionUtils.handleReflectionException(e);
		}
	}

	/**
	 * url参数未定义method时的默认Action函数. 默认为index Action.
	 */
	public ActionForward unspecified(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		return list(mapping, form, request, response);
	}
	
	/**
	 * 列出所有对象的Action函数.
	 */
	public ActionForward list(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		List filters = PropertyFilter.buildFromHttpRequest(request);
		Page page = PropertyFilter.buildPageFromHttpRequest(request,REQUEST_PAGE);
		//设置默认排序方式
		if (!page.isOrderBySetted()) {
			page.setOrderBy(idName);
			page.setOrder(Page.ASC);
		}
		//设置默认查询条件
		PropertyFilter filter = new PropertyFilter(Constants.FILTER_NAME, Constants.STATUS_VALID);
		filters.add(filter);
		page = getEntityManager().findPage(page, filters);
		request.setAttribute(REQUEST_PAGE, page);
		// 为子类扩展操作
		refrenceData(form,request,null);
		return mapping.findForward(LIST);
	}
	
	/**
	 * 显示修改对象Form的Action函数.
	 */
	public ActionForward edit(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		// 防止重复提交的token
		saveToken(request);
		
		Object object = initEntity(request);
		if (id != null && object == null) {
			saveError(request, "entity.missing");
			return list(mapping, form, request, response);
		}
//		if (id == null){
//			try {
//				object = getEntityClass().newInstance();
//			} catch (InstantiationException e) {
//				log.error(e);
//			} catch (IllegalAccessException e) {
//				log.error(e);
//			}
//		}
		
		bindForm(form,object);
		//为子类扩展操作
		onInitForm(form, request, object);
		// 为子类扩展操作
		refrenceData(form,request,object);
		return mapping.findForward(EDIT);
	}

	/**
	 * 保存对象的Action函数.
	 */
	public ActionForward save(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		//验证TOKEN，防止重复提交
		if(!validateToken(request)) return list(mapping, form, request, response);
		
		Object object = initEntity(request);
		if(object == null) object = doNewEntity();
		
		//save操作前的验证
		ActionForward errorForward = validateBeforeSave(object,mapping, form, request, response);
		if(errorForward != null) return errorForward;
		
		// 将lazyform内容绑定到object
		bindEntity(form, object);
		// 为子类扩展操作
		onInitEntity(form, request, object);
		
		// 为保存操作添加创建人更新人等信息
		BaseEntity baseEntity = addSaveData(object);
		doSaveEntity(request, baseEntity);
		saveMessage(request, "entity.saved");

		return mapping.findForward(SUCCESS);
	}
	
	/**
	 * 查看业务对象（不能修改）的Action函数.
	 */
	public ActionForward view(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		Object object = initEntity(request);
		if (object == null) {
			saveError(request, "entity.missing");
			return list(mapping, form, request, response);
		}
		request.setAttribute(REQUEST_ENTITY, object);
		// 为子类扩展操作
		refrenceData(form,request,object);
		return mapping.findForward(VIEW);
	}

	/**
	 * 标记删除单个对象的Action函数.
	 */
	public ActionForward erase(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		Object object = initEntity(request);
		if(object == null){
			saveDirectlyError(request, "操作失败：记录不存在");
			return list(mapping, form, request, response);
		}
		
		//为保存操作添加创建人更新人等信息
		BaseEntity baseEntity = addEraseData(object);
		doEraseEntity(request, baseEntity);
		saveMessage(request, "entity.deleted");

		return mapping.findForward(SUCCESS);
	}
	
//	/**
//	 * 删除单个对象的Action函数.
//	 */
//	public ActionForward delete(ActionMapping mapping, ActionForm form,
//			HttpServletRequest request, HttpServletResponse response) {
//		Object object = initEntity(request);
//		if(object == null){
//			saveDirectlyError(request, "操作失败：记录不存在");
//			return list(mapping, form, request, response);
//		}
//		try {
//			doDeleteEntity(request, object);
//			saveMessage(request, "entity.deleted");
//		} catch (Exception e) {
//			saveDirectlyError(request, e.getMessage());
//		}
//		return mapping.findForward(SUCCESS);
//	}
	
	/**
	 * 验证TOKEN
	 * @param request
	 * @return
	 */
	protected boolean validateToken(HttpServletRequest request){
		if (isCancelled(request))
			return false;
		if (!isTokenValid(request)) {
			saveDirectlyError(request, "重复提交");
			return false;
		}
		resetToken(request);
		return true;
	}
	
	/**
	 * save操作前的验证
	 * @param object
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return
	 */
	protected ActionForward validateBeforeSave(Object object,ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response){
		// run validation rules on this form
		ActionMessages errors = form.validate(mapping, request);
		if (!errors.isEmpty()) {
			saveErrors(request, errors);
			resetToken(request);
			return edit(mapping, form, request, response);
		}

		if (object == null) {
			saveError(request, "entity.missing");
			resetToken(request);
			return list(mapping, form, request, response);
		}
		return null;
	}
	
	/**
	 * 为保存操作添加创建人更新人等信息，保存操作专用
	 * @param isNewEntity 是否创建新对象
	 * @param object
	 * @return
	 */
	protected BaseEntity addSaveData(Object object){
		//保存创建人更新人
		BaseEntity baseEntity = (BaseEntity) object;
		Long userId = CommonUtils.getCurrentUserId();
		if(userId == null) userId = new Long(0);
		//新增
		if(id == null){
			baseEntity.setStatus(Constants.STATUS_VALID);
			baseEntity.setCreator(userId);
			baseEntity.setCreated(new Date());
		}else {//修改
			baseEntity.setModificator(userId);
			baseEntity.setModified(new Date());
		}
		return baseEntity;
	}
	
	/**
	 * 为标记删除操作添加更新人等信息，标记删除操作专用
	 * @param isNewEntity 是否创建新对象
	 * @param object
	 * @return
	 */
	protected BaseEntity addEraseData(Object object){
		//保存更新人
		BaseEntity baseEntity = (BaseEntity) object;
		Long userId = CommonUtils.getCurrentUserId();
		if(userId == null) userId = new Long(0);
		baseEntity.setStatus(Constants.STATUS_INVALID);
		baseEntity.setModificator(userId);
		baseEntity.setModified(new Date());
		return baseEntity;
	}
	
	/**
	 * 初始化Entity，用于edit,save,view,erase等操作
	 */
	protected Object initEntity(HttpServletRequest request) {
		id = null;
		String idString = request.getParameter(idName);
		try {
			id = (Serializable) ConvertUtils.convert(idString, idClass);
		} catch (NumberFormatException e) {
			throw new IllegalArgumentException("Wrong when get id from request");
		}
		
		Object object = null;
		if (id != null) {
			object = doGetEntity(request, id);
		}
		return object;
	}
	/**
	 * 新建业务对象的函数.
	 */
	protected Object doNewEntity() {
		Object object = null;
		try {
			object = getEntityClass().newInstance();
		} catch (Exception e) {
			log.error("Can't new Instance of entity.", e);
		}
		return object;
	}
	
	/**
	 * 显示Form表单时的回调函数.为Form对象添加更多属性,在子类重载.
	 */
	protected void onInitForm(ActionForm form, HttpServletRequest request,
			Object object) {
	}

	/**
	 * 保存Form表单时的回调函数.为业务对象添加更多属性，在子类重载.
	 */
	protected void onInitEntity(ActionForm form, HttpServletRequest request,
			Object object) {
	}
	/**
	 * 从数据库获取业务对象的函数.
	 */
	protected Object doGetEntity(HttpServletRequest request,Serializable id) {
		return getEntityManager().get(id);
	}
	/**
	 * 保存业务对象的函数.
	 */
	protected void doSaveEntity(HttpServletRequest request,Object object) {
		getEntityManager().save(object);
	}

	/**
	 * 标记删除业务对象的函数.
	 */
	protected void doEraseEntity(HttpServletRequest request,Object object) {
		getEntityManager().save(object);
	}
	
	/**
	 * 删除业务对象的函数.
	 */
	protected void doDeleteEntity(HttpServletRequest request,Object object) {
		getEntityManager().delete(object);
	}
	
	/**
	 * form与list界面所需的参考对象注入.如categoryList,在子类重载.
	 */
	protected void refrenceData(ActionForm form,HttpServletRequest request,
			Object object) {
	}
}
